from PyQt4.QtCore import pyqtSignal
from PyQt4.QtCore import QObject, QString
from PyQt4.QtGui import qApp
from PyQt4 import QtCore
import gobject

import pygst
import time
import glib

pygst.require('0.10')
gobject.threads_init()
import gst
import thread, time

class Player(QObject):
    """
        GStreamer base player
    """

    tick = QtCore.pyqtSignal(int)
    stateChanged = QtCore.pyqtSignal(gst.State, gst.State)
    sourceChanged = QtCore.pyqtSignal()
    finished = QtCore.pyqtSignal()

    currentSong = None

    def __init__(self, phonik):
        QObject.__init__(self)

        self.phonik = phonik

        self.playbin = gst.element_factory_make("playbin2", "player")
        fakesink = gst.element_factory_make("fakesink", "fakesink")
        self.playbin.set_property("video-sink", fakesink)

        self.bus = self.playbin.get_bus()
        self.bus.add_signal_watch()
        self.bus.enable_sync_message_emission()
        self.bus.connect('message', self._onMessage)
        thread.start_new_thread(self._timer, ())


    def _timer(self):
        while True:
            time.sleep(0.1)
            pos = self.getPosition()
            if pos:
                self.tick.emit(pos)


    def getPosition(self):
        if self.playbin.get_state()[1] == gst.STATE_PLAYING:
            try:
                nstime = self.playbin.query_position(gst.FORMAT_TIME, None)[0]
                return self._convertNS(nstime)
            except gst.QueryError:
                return 0


    def getDuration(self):
        try:
            nstime = self.playbin.query_duration(gst.FORMAT_TIME, None)[0]
            return self._convertNS(nstime)
        except gst.QueryError:
            return -1

    def getCurrentSong(self):
        return   self.currentSong


    def isStopped(self):
        if self.playbin.get_state()[1] == gst.STATE_NULL:
            return True
        else:
            return False

    def isPlaying(self):
        if self.playbin.get_state()[1] == gst.STATE_PLAYING:
            return True
        else:
            return False



    def _onMessage(self, bus, message):
        """
            Called when a message is received from gstreamer
        """
        # print message.type
        if message.type == gst.MESSAGE_NEW_CLOCK:
            self.sourceChanged.emit()

        elif message.type == gst.MESSAGE_EOS:
            self.currentSong = None
            self.finished.emit()

        elif message.type == gst.MESSAGE_ERROR:
            err = message.parse_error()[0]
            self.playbin.set_state(gst.STATE_NULL)
            self.phonik.notify(err.message)


        elif message.type == gst.MESSAGE_STATE_CHANGED:
            if message.src == self.playbin:
                oldstate, newstate, pending = message.parse_state_changed()
                self.stateChanged.emit(oldstate, newstate)
                
        return True


    def _convertNS(self, t):
        s, ns = divmod(t, 1000000000)
        return s


    def play(self, path=None):
        print 'play ', path
        path = str(path)
        if path:
            self.playbin.set_state(gst.STATE_NULL)
            try:
                if '://' in path:
                    self.playbin.set_property("uri", path)
                else:
                    self.playbin.set_property("uri", "file://" + path)
                self.currentSong = path
            except TypeError, te:
                print te, ': ', path
            except Exception, e:
                print e

        self.playbin.set_state(gst.STATE_PLAYING)


    def isPlaying(self):
        return self.playbin.get_state()[1] == gst.STATE_PLAYING

    def isPaused(self):
        return self.playbin.get_state()[1] == gst.STATE_PAUSED


    def pause(self):
        if self.isPlaying():
            self.playbin.set_state(gst.STATE_PAUSED)
        elif self.isPaused():
            self.playbin.set_state(gst.STATE_PLAYING)


    def stop(self):
        if self.isPlaying() or self.isPaused():
            self.playbin.set_state(gst.STATE_NULL)
            return True
        return False


    def setVolume(self, volume):
        self.playbin.set_property("volume", float(volume) / 100)


    def getVolume(self):
        return self.playbin.get_property("volume")


    def seek(self, pos):
        self.playbin.seek_simple(gst.FORMAT_TIME, gst.SEEK_FLAG_FLUSH, pos * 1000000000)


        

        


